/*
 * Copyright (c) 2024 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#include <devmon/driver_abi.h>
#include <dlfcn.h>
#include <gtest/gtest.h>
#include <test_utilities/test_base.h>
#include <mc/common.h>

#include "test_hi182x_common.h"

using namespace dev;

namespace drivers {
namespace pcie_nic_card {
namespace hisi {
namespace test {

// ========================= 驱动注册功能测试 =========================

TEST_F(Hi182xAbiTest, register_device_driver_success) {
    // 目标：验证hi182x驱动注册成功，并返回正确数量的设备类型
    // 验证驱动注册返回3种设备类型
    EXPECT_EQ(m_devices.size(), 3);
    
    // 验证包含网卡设备类型
    EXPECT_TRUE(m_devices.find("PCIeNicCard") != m_devices.end());
    
    // 验证包含网口设备类型
    EXPECT_TRUE(m_devices.find("NicPort") != m_devices.end());
    
    // 验证包含光模块设备类型
    EXPECT_TRUE(m_devices.find("OpticalTransceiver") != m_devices.end());
}

TEST_F(Hi182xAbiTest, device_driver_structure_validation) {
    // 目标：验证每个设备驱动的ABI接口完整性
    for (const auto& [device_name, device_driver] : m_devices) {
        // 验证设备名称非空
        EXPECT_FALSE(std::string(device_driver->device_name).empty());
        
        // 验证构造函数指针有效
        EXPECT_TRUE(device_driver->ctor != nullptr);
        
        // 验证初始化函数指针有效
        EXPECT_TRUE(device_driver->init != nullptr);
        
        // 验证启动函数指针有效
        EXPECT_TRUE(device_driver->start != nullptr);
        
        // 验证停止函数指针有效
        EXPECT_TRUE(device_driver->stop != nullptr);
    }
}

// ========================= 错误处理测试 =========================

TEST_F(Hi182xAbiTest, device_pcienicard_with_null_device) {
    // 目标：验证PCIeNicCard设备对空指针参数的错误处理能力
    auto device_driver = m_devices["PCIeNicCard"];
    ASSERT_TRUE(device_driver != nullptr);

    // 测试：传入nullptr设备名称，应返回nullptr
    void* device = device_driver->ctor(&m_test_service, nullptr);
    EXPECT_EQ(device, nullptr);

    // 测试：传入nullptr服务指针，应返回nullptr
    device = device_driver->ctor(nullptr, "hi182x_card_null_params");
    EXPECT_EQ(device, nullptr);

    // 测试：init函数传入nullptr设备指针，应返回错误
    status_t init_ret = device_driver->init(nullptr, nullptr, nullptr);
    EXPECT_EQ(init_ret, STATUS_ERROR);

    // 测试：start函数传入nullptr设备指针，应返回错误
    status_t start_ret = device_driver->start(nullptr);
    EXPECT_EQ(start_ret, STATUS_ERROR);

    // 测试：stop函数传入nullptr设备指针，应返回错误
    status_t stop_ret = device_driver->stop(nullptr);
    EXPECT_EQ(stop_ret, STATUS_ERROR);
}

TEST_F(Hi182xAbiTest, device_networkport_with_null_params) {
    // 目标：验证NicPort设备对空指针参数的错误处理能力
    auto device_driver = m_devices["NicPort"];
    ASSERT_TRUE(device_driver != nullptr);

    // 测试：传入nullptr设备名称，应返回nullptr
    void* device = device_driver->ctor(&m_test_service, nullptr);
    EXPECT_EQ(device, nullptr);

    // 测试：传入nullptr服务指针，应返回nullptr
    device = device_driver->ctor(nullptr, "hi182x_port_null_params");
    EXPECT_EQ(device, nullptr);

    // 测试：init函数传入nullptr，应返回错误
    status_t init_ret = device_driver->init(nullptr, nullptr, nullptr);
    EXPECT_EQ(init_ret, STATUS_ERROR);

    // 测试：start函数传入nullptr，应返回错误
    status_t start_ret = device_driver->start(nullptr);
    EXPECT_EQ(start_ret, STATUS_ERROR);

    // 测试：stop函数传入nullptr，应返回错误
    status_t stop_ret = device_driver->stop(nullptr);
    EXPECT_EQ(stop_ret, STATUS_ERROR);
}

TEST_F(Hi182xAbiTest, device_opticalmodule_with_null_params) {
    // 目标：验证OpticalTransceiver设备对空指针参数的错误处理能力
    auto device_driver = m_devices["OpticalTransceiver"];
    ASSERT_TRUE(device_driver != nullptr);

    // 测试：传入nullptr设备名称，应返回nullptr
    void* device = device_driver->ctor(&m_test_service, nullptr);
    EXPECT_EQ(device, nullptr);

    // 测试：传入nullptr服务指针，应返回nullptr
    device = device_driver->ctor(nullptr, "hi182x_optical_module_null_params");
    EXPECT_EQ(device, nullptr);

    // 测试：init函数传入nullptr，应返回错误
    status_t init_ret = device_driver->init(nullptr, nullptr, nullptr);
    EXPECT_EQ(init_ret, STATUS_ERROR);

    // 测试：start函数传入nullptr，应返回错误
    status_t start_ret = device_driver->start(nullptr);
    EXPECT_EQ(start_ret, STATUS_ERROR);

    // 测试：stop函数传入nullptr，应返回错误
    status_t stop_ret = device_driver->stop(nullptr);
    EXPECT_EQ(stop_ret, STATUS_ERROR);
}

// ========================= 多设备并发测试 =========================

TEST_F(Hi182xAbiTest, multiple_devices_creation) {
    // 目标：验证系统支持同时创建多个不同类型的设备实例
    // 场景：模拟多网卡、多网口、多光模块的真实使用场景
    std::vector<driver_handle_t> pcie_nic_card_devices;
    std::vector<driver_handle_t> network_port_devices;
    std::vector<driver_handle_t> optical_module_devices;

    // 创建3个PCIeNicCard设备实例
    auto card_driver = m_devices["PCIeNicCard"];
    for (int i = 0; i < 3; ++i) {
        std::string device_name = "hi182x_card_" + std::to_string(i);
        auto        device      = card_driver->ctor(&m_test_service, device_name.c_str());
        ASSERT_TRUE(device != nullptr);
        pcie_nic_card_devices.push_back(device);
    }

    // 创建3个NetworkPort设备实例
    auto port_driver = m_devices["NicPort"];
    for (int i = 0; i < 3; ++i) {
        std::string device_name = "hi182x_port_" + std::to_string(i);
        auto        device      = port_driver->ctor(&m_test_service, device_name.c_str());
        ASSERT_TRUE(device != nullptr);
        network_port_devices.push_back(device);
    }

    // 创建3个OpticalModule设备实例
    auto om_driver = m_devices["OpticalTransceiver"];
    for (int i = 0; i < 3; ++i) {
        std::string device_name = "hi182x_om_" + std::to_string(i);
        auto        device      = om_driver->ctor(&m_test_service, device_name.c_str());
        ASSERT_TRUE(device != nullptr);
        optical_module_devices.push_back(device);
    }

    // 验证所有设备创建成功
    EXPECT_EQ(pcie_nic_card_devices.size(), 3);
    EXPECT_EQ(network_port_devices.size(), 3);
    EXPECT_EQ(optical_module_devices.size(), 3);
}

} // namespace test
} // namespace hisi
} // namespace pcie_nic_card
} // namespace drivers
